//
//  WCISecurity.m
//  AFBrowser
//
//  Created by alfie on 2020/9/9.
//

#import "WCISecurity.h"
#import <CommonCrypto/CommonCrypto.h>
#import "RSAEncryptor.h"
static const NSString * AES_Key = @"thisis32bitlongpassphraseijixina";
@interface WCISecurity ()

@property (nonatomic, assign) int keySize;

@property (nonatomic, assign) int blockSize;

/** 密钥 */
@property (nonatomic, copy) NSString            *keyString;

@end



@implementation WCISecurity


+ (instancetype)sharedSecurity {
    static WCISecurity *instance;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
        instance.algorithm = kCCAlgorithmAES;
    });
    
    return instance;
}

- (void)setAlgorithm:(uint32_t)algorithm {
    _algorithm = algorithm;
    switch (algorithm) {
        case kCCAlgorithmAES:
            self.keySize = kCCKeySizeAES128;
            self.blockSize = kCCBlockSizeAES128;
            break;
        case kCCAlgorithmDES:
            self.keySize = kCCKeySizeDES;
            self.blockSize = kCCBlockSizeDES;
            break;
        default:
            break;
    }
}

- (NSString *)encryptString:(NSString *)string {
    
    // 设置秘钥
    NSData *keyData = [self.keyString dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t cKey[self.keySize];
    bzero(cKey, sizeof(cKey));
    [keyData getBytes:cKey length:self.keySize];
    
    // 设置iv
    uint8_t cIv[self.blockSize];
    bzero(cIv, self.blockSize);
    int option = 0;
    NSData *iv = [self.keyString dataUsingEncoding:(NSUTF8StringEncoding)];
    if (iv) {
        [iv getBytes:cIv length:self.blockSize];
        option = kCCOptionPKCS7Padding;
    } else {
        option = kCCOptionPKCS7Padding | kCCOptionECBMode;
    }
    
    // 设置输出缓冲区
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    size_t bufferSize = [data length] + self.blockSize;
    void *buffer = malloc(bufferSize);
    
    // 开始加密
    size_t encryptedSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          self.algorithm,
                                          option,
                                          cKey,
                                          self.keySize,
                                          cIv,
                                          [data bytes],
                                          [data length],
                                          buffer,
                                          bufferSize,
                                          &encryptedSize);
    
    NSData *result = nil;
    if (cryptStatus == kCCSuccess) {
        result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
    } else {
        free(buffer);
        NSLog(@"[错误] 加密失败|状态编码: %d", cryptStatus);
    }
    
    NSString *resultStr = [result base64EncodedStringWithOptions:0];
    resultStr = [resultStr stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    resultStr = [resultStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    resultStr = [resultStr stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    resultStr = [resultStr stringByReplacingOccurrencesOfString:@" "  withString:@""];
    return resultStr;
}

- (NSString *)decryptString:(NSString *)string {
    //闪退问题
    if (string == nil) return @"";
    NSString *str = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    str = [str stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    str = [str stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // 设置秘钥
    NSData *keyData = [self.keyString dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t cKey[self.keySize];
    bzero(cKey, sizeof(cKey));
    [keyData getBytes:cKey length:self.keySize];
    NSData *iv = [self.keyString dataUsingEncoding:(NSUTF8StringEncoding)];

    // 设置iv
    uint8_t cIv[self.blockSize];
    bzero(cIv, self.blockSize);
    int option = 0;
    if (iv) {
        [iv getBytes:cIv length:self.blockSize];
        option = kCCOptionPKCS7Padding;
    } else {
        option = kCCOptionPKCS7Padding | kCCOptionECBMode;
    }
    
    // 设置输出缓冲区
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:0];
    size_t bufferSize = [data length] + self.blockSize;
    void *buffer = malloc(bufferSize);
    
    // 开始解密
    size_t decryptedSize = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          self.algorithm,
                                          option,
                                          cKey,
                                          self.keySize,
                                          cIv,
                                          [data bytes],
                                          [data length],
                                          buffer,
                                          bufferSize,
                                          &decryptedSize);
    
    NSData *result = nil;
    if (cryptStatus == kCCSuccess) {
        result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
    } else {
        free(buffer);
        NSLog(@"[错误] 解密失败|状态编码: %d", cryptStatus);
    }
    
    return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
}


- (NSString *)keyString {
    if (!_keyString) {
//        NSString *rasKey = [MOModuleService rsaKey];
//        _keyString = [RSAEncryptor decryptString:rasKey privateKey:private_key];
//        if (!_keyString) {
            _keyString = @"htfvjredhjhghpsy";
//        }
    }
    return _keyString;
}

+ (NSData *)pkcs7Padding:(NSData *)data blockSize:(size_t)blockSize {
    NSUInteger padding = blockSize - (data.length % blockSize);
    NSMutableData *paddedData = [NSMutableData dataWithData:data];
    for (NSUInteger i = 0; i < padding; i++) {
        [paddedData appendBytes:&padding length:1];
    }
    return paddedData;
}


+ (NSString *)encryptAES256:(NSString *)plaintext error:(NSError **)error{
    NSData *keyData = [AES_Key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *plaintextData = [plaintext dataUsingEncoding:NSUTF8StringEncoding];
    
    // PKCS7 padding
    NSData *paddedData = [self pkcs7Padding:plaintextData blockSize:kCCBlockSizeAES128];
    
    // Prepare buffer for ciphertext
    size_t cipherBufferSize = paddedData.length + kCCBlockSizeAES128;
    void *cipherBuffer = malloc(cipherBufferSize);
    
    // Generate random IV
    NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
    if (SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, iv.mutableBytes) != errSecSuccess) {
        if (error) {
            *error = [NSError errorWithDomain:@"AES" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Failed to generate random IV."}];
        }
        free(cipherBuffer);
        [MOXLogUntil LogNomalWithString:@"[header] : encryptAES256 iv获取失败"];
        return nil;
    }

    // Perform encryption
    size_t numBytesEncrypted = 0;
    CCCryptorStatus result = CCCrypt(kCCEncrypt,
                                     kCCAlgorithmAES,
                                     kCCOptionPKCS7Padding,
                                     keyData.bytes,
                                     kCCKeySizeAES256,
                                     iv.bytes,
                                     paddedData.bytes,
                                     paddedData.length,
                                     cipherBuffer,
                                     cipherBufferSize,
                                     &numBytesEncrypted);

    if (result != kCCSuccess) {
        if (error) {
            *error = [NSError errorWithDomain:@"AES" code:result userInfo:@{NSLocalizedDescriptionKey: @"Encryption failed."}];
        }
        free(cipherBuffer);
        [MOXLogUntil LogNomalWithString:@"[header] : encryptAES256 Encryption failed"];

        return nil;
    }

    // Create final ciphertext
    NSData *cipherData = [NSData dataWithBytes:cipherBuffer length:numBytesEncrypted];
    free(cipherBuffer);

    // Combine IV and ciphertext
    NSMutableData *resultData = [NSMutableData dataWithData:iv];
    [resultData appendData:cipherData];

    // Return Base64 encoded string
    return [resultData base64EncodedStringWithOptions:0];
}

+ (NSString *)decryptAES256:(NSString *)ciphertext error:(NSError **)error{
    NSData *keyData = [AES_Key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipherData = [[NSData alloc] initWithBase64EncodedString:ciphertext options:0];
    
    // Extract IV
    NSData *iv = [cipherData subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
    NSData *encryptedData = [cipherData subdataWithRange:NSMakeRange(kCCBlockSizeAES128, cipherData.length - kCCBlockSizeAES128)];

    // Prepare buffer for decrypted data
    size_t decryptedBufferSize = encryptedData.length + kCCBlockSizeAES128;
    void *decryptedBuffer = malloc(decryptedBufferSize);
    
    // Perform decryption
    size_t numBytesDecrypted = 0;
    CCCryptorStatus result = CCCrypt(kCCDecrypt,
                                     kCCAlgorithmAES,
                                     kCCOptionPKCS7Padding,
                                     keyData.bytes,
                                     kCCKeySizeAES256,
                                     iv.bytes,
                                     encryptedData.bytes,
                                     encryptedData.length,
                                     decryptedBuffer,
                                     decryptedBufferSize,
                                     &numBytesDecrypted);

    if (result != kCCSuccess) {
        if (error) {
            *error = [NSError errorWithDomain:@"AES" code:result userInfo:@{NSLocalizedDescriptionKey: @"Decryption failed."}];
        }
        free(decryptedBuffer);
        return nil;
    }

    // Create final decrypted data
    NSData *decryptedData = [NSData dataWithBytes:decryptedBuffer length:numBytesDecrypted];
    free(decryptedBuffer);

    return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
}

@end
